#pragma once

#include <string>
#include <map>
#include "Utilities.h"

#include "XMLNode.h"

namespace tinyxml2
{
    class XMLDocument;
    class XMLElement;
    class XMLNode;
}

namespace ZeEngine
{
    typedef std::multimap<std::string, std::string> XMLMap;
    typedef std::pair<std::string, std::string>     XMLMapPair;

    class XMLParsers
    {
        public:
            XMLParsers(const std::string& iFileName);
            ~XMLParsers();

            //Helper functions
            std::string GetValueString(const std::string& iPath);
            std::string GetAttributeString(const std::string& iPath);

            s32 GetValueInt(const std::string& iPath);
            s32 GetAttributeInt(const std::string& iPath);

            f32 GetValueFloat(const std::string& iPath);
            f32 GetAttributeFloat(const std::string& iPath);

            //Generic function
            template <typename T>
            T GetValue(const std::string& iPath)
            {
                return Utilities::ConvertStringToType<T>(Search(iPath, *m_pValueMap));
            }

            template <typename T>
            T GetAttribute(const std::string& iPath)
            {
                return Utilities::ConvertStringToType<T>(Search(iPath, *m_pAttributeMap));
            }

            inline void SetPath(const std::string& iPath) { m_Path = iPath + "."; }

            inline bool IsLoaded() { return m_Loaded; }

            bool ValueExists(const std::string& iPath);
            bool AttributeExists(const std::string& iPath);

            XMLNodeList GetNodeList(const std::string& iPath);

        private:

            std::string Search(const std::string& iPath, const XMLMap& iMap);
            void LoadDocument();
            void ParseXML(tinyxml2::XMLElement* pParentElement, std::string iCurrentPath = "");
            void ParseXML(tinyxml2::XMLElement* pParentElement, XMLNode& oNode);

            std::string                 m_FileName;
            std::string                 m_Path;
            bool                        m_Loaded;
            tinyxml2::XMLDocument*      m_pDocument;
            XMLMap*                     m_pValueMap;
            XMLMap*                     m_pAttributeMap;

            XMLNode                     m_Root;

    };
}
